/****************************************************************************
*
* Copyright(c) 2023  C*Core -   All Rights Reserved
*
* THIS SOFTWARE IS DISTRIBUTED "AS IS, " AND ALL WARRANTIES ARE DISCLAIMED,
* INCLUDING MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* PROJECT     : CCFC2011BC
* DESCRIPTION : intc demo code
* HISTORY     : Initial version.
* @file     intc_demo.c
* @version  1.1
* @date     2023 - 02 - 20
* @brief    Initial version.
*
*****************************************************************************/
#include "intc_demo.h"
#include "console.h"
#include "intc_lld.h"
#include "e200z3_asm.h"

/*******************************************************************************
 * @brief      UserEccDemo
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void UserEccDemo(void)
{
    /* Some operations trigger ECC */
}

/*******************************************************************************
 * @brief      EccExceptionHandler_withoutIntc_Demo
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void EccExceptionHandler_withoutIntc_Demo(void)
{
    uint32_t temp_MSR;      /* e200z_ Machine State Register(MSR) */
    uint32_t temp_INTC_CPR; /* INTC Current Priority REG(INTC_CPR) */

    /* 1.**************************
     * Setup ECC detection method */
    /* Save old MSR and disable MSR_EE */
    MFMSR(temp_MSR); /* PRQA S 1006 */
    DIS_MSR_EE(); /* PRQA S 1006 */

    /* If MSR_EE is off before Demo, change the current interrupt
     * priority to prevent unnecessary external interrupts */
    if ((temp_MSR & MSR_EE) == 0U)
    {
        /* Save old INTC_CPR */
        temp_INTC_CPR = INTC_GET_CPR(); /* PRQA S 3469 */
        /* Set the current priority to the highest */
        INTC_IRQ_Disable();
    }

    /* Enable MSR_EE to prevent ECC errors during read */
    MTMSR(MSR_EE); /* PRQA S 1006 */

    /* 2.**************************
     * User ECC Demo */
    UserEccDemo(); /* PRQA S 2987 */

    /* 3.**************************
     * Restore MSR & INTC.CPR */
    /* Restore MSR */
    MTMSR(temp_MSR); /* PRQA S 1006 */

    /* If MSR_EE is off before reading Flash, Restore INTC_CPR */
    if ((temp_MSR & MSR_EE) == 0U)
    {
        /* Restore INTC_CPR */
        INTC_CPR_SET(temp_INTC_CPR);
    }
}

/*******************************************************************************
 * @brief      EIRQ0_Init
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void EIRQ0_Init(void)
{
    SIUL_Init_EIRQ((uint8_t)PA3_PCR);                    /* Pin PA[3] - EIRQ0 configured as GPIO, input, pull up enable */
    SIUL_IntFallingEventEnable((uint32_t)IFEER_IFEE0);    /* Enable falling edge event on EIRQ0 */
    SIUL_EXT_IntReqEnable((uint32_t)IRER_IRE0);           /* Enable interrupt EIRQ0 */
}

/*******************************************************************************
 * @brief      SIUL_EXTI_Callback
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
static void SIUL_EXTI_Callback(void)
{
    /* There's single interrupt vector for 8 IRQs. Test if interrupt comes from IRQ0: */
    if (SIUL_EXTI_Get_Flag() == (uint32_t)ISR_EIF0)
    {
        LED1_TOGGLE;                    /* toggle LED */
        SIUL_EXTI_Clear_Flag((uint32_t)ISR_EIF0); /* Clear interrupt flag */
    }
    else
    {
        /* ... */
    }
}

/*******************************************************************************
 * @brief      INTC_EIRQ0_LED_Demo
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void INTC_EIRQ0_LED_Demo(void) /* PRQA S 1505 */
{
    EIRQ0_Init();

    INTC_SoftInit(SIUL_EXTI_Callback, (uint16_t)SIU_EXTI0_7_IRQn, (uint8_t)PSR_PRI_1);

    INTC_IRQ_Enable();   /* Set the current priority */

    (void)PSPRINTF("\n INTC_RTC_LED_Demo Start!\n");
    (void)PSPRINTF("\n LED1 flash in PA3 falling edge!\n");
}

#if 1
/*******************************************************************************
 * @brief      RTC_INT_Init
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void RTC_INT_Init(void) /* PRQA S 1505 */
{
    /* Set the clock frequency to 500KHz
     * If the RTC matches the 10 to 21 bits of the RTCCNT,
     * the minimum count unit is 2us x 1024 = 2, 048 us
     * */
    RTC.RTCC.B.CLKSEL = 0x2;    /* Select the 16MHz FIRC as the clock source */
    RTC.RTCC.B.DIV32EN = 1;     /* Frequency division:32, frequency = 500khz, period = 2us*/
    RTC.RTCC.B.DIV512EN = 0;    /* The 512 division factor is not enabled */
    RTC.RTCC.B.FRZEN = 1;       /* The clock stops in freeze mode */
    RTC.RTCC.B.CNTEN = 1;       /* Enable counter */
    RTC.RTCC.B.RTCIE = 1;       /* Enable RTC interrupt */
}

/*******************************************************************************
 * @brief      RTC_IT_Callback
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void RTC_IT_Callback(void) /* PRQA S 1505 */
{
    LED3_TOGGLE;            /* Change LED status */

    /* Reset time: 244*2048us = 499712us = 0.5s */
    RTC.RTCC.B.RTCVAL = 0x00000fffU &((RTC.RTCCNT.R >> 10U) + 244U);

    if (RTC.RTCC.B.RTCVAL == 0U)
    {
        RTC.RTCC.B.RTCVAL = 1;
    }

    RTC.RTCS.B.RTCF = 1;    /* Clear interrupt flag */
}

/*******************************************************************************
 * @brief      INTC_RTC_LED_Demo
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void INTC_RTC_LED_Demo(void)
{
    RTC_INT_Init();

    INTC_SoftInit(RTC_IT_Callback, (uint16_t)RTC_IRQn, (uint8_t)PSR_PRI_1);

    INTC_IRQ_Enable();   /* Set the current priority */
    (void)PSPRINTF("\n INTC_RTC_LED_Demo Start!\n");
    (void)PSPRINTF("\n LED3 flash in 0.5s!\n");

    /* Reset time: 244*2048us = 499712us = 0.5s */
    RTC.RTCC.B.RTCVAL = 0x00000fffU &((RTC.RTCCNT.R >> 10U) + 244U);
}
#endif

/*******************************************************************************
 * @brief      INTC_Test_Demo
 * @param[in]  None
 * @param[out] None
 * @retval     None
 * @notapi
 *******************************************************************************/
void INTC_Test_Demo(void)
{
	/* Function RTC LED Demo Test */
#if INTC_RTC_DEMO_SW
    INTC_RTC_LED_Demo();
#endif

    /* Function PA[3] SIU Interrupt Test */
#if INTC_EIRQ0_DEMO_SW
    INTC_EIRQ0_LED_Demo();
#endif
}
